﻿using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.IO;
using System.Text;

namespace Mes5GService.MES
{
    public class BopTreeConverter
    {
        private static Dictionary<string, ColumnType> DynamicField = new Dictionary<string, ColumnType>()
        {
            {"SpotRecord",ColumnType.Spotrecord },
            {"SerialNum",ColumnType.Text },
            {"ParentProductNum",ColumnType.Text },
            {"ParentProductName",ColumnType.Text },
            {"FisrtDrawingNum",ColumnType.Text },
            {"SecondDrawingName",ColumnType.Text },
            {"AbnormalRecord",ColumnType.Text },
            {"SecondToolUsed",ColumnType.Text },
            {"ThirdToolUsed",ColumnType.Text },
            {"AtmPressure",ColumnType.Text },
            {"ThirdMeasuredValues",ColumnType.Text },
            {"FourthMeasuredValues",ColumnType.Text },
            {"SecondPhotoNo",ColumnType.Photo },
            {"ThirdPhotoNo",ColumnType.Photo },
            {"FourthPhotoNo",ColumnType.Photo },

            {"FirstDrawingName",ColumnType.Text },
            {"SecondDrawingNum",ColumnType.Text },
            {"Certificate",ColumnType.Text },
            {"Remarks",ColumnType.Text },
            {"FirstOperator",ColumnType.Signature },
            {"FirstOperatorData",ColumnType.Signatureopt },
            {"FirstOperatorUser",ColumnType.Signatureopt },
            {"SecondOperator",ColumnType.Signature },
            {"SecondOperatorData",ColumnType.Signatureopt },
            {"SecondOperatorUser",ColumnType.Signatureopt },
            {"ThirdOperator",ColumnType.Signature },
            {"ThirdOperatorData",ColumnType.Signatureopt },
            {"ThirdOperatorUser",ColumnType.Signatureopt },

            {"ProductNum",ColumnType.Text },

            {"FourthOperator",ColumnType.Signature },
            {"FourthOperatorData",ColumnType.Signatureopt },
            {"FourthOperatorUser",ColumnType.Signatureopt },
            {"FifthOperator",ColumnType.Signature },
            {"FifthOperatorData",ColumnType.Signatureopt },
            {"FifthOperatorUser",ColumnType.Signatureopt },

            {"DesignerDemand",ColumnType.Text },
            {"ProcessorDemand",ColumnType.Text },
            {"ToolUsed",ColumnType.Text },

            {"RecordLocation",ColumnType.Text },
            {"PhotoNo",ColumnType.Photo },
            {"SecondMeasuredValues",ColumnType.Text },
            {"Temperature",ColumnType.Text },
            {"Humidity",ColumnType.Text },
            {"Model",ColumnType.Text },
            {"RecordStatus",ColumnType.Text },
            {"RecordMainopoint",ColumnType.Text },

            {"RecordElement",ColumnType.Text },
            {"RecordRequire",ColumnType.Text },
            {"FirstMeasuredValues",ColumnType.Text },
            {"FirstConfirmResult",ColumnType.Boolean },
            {"SecondConfirmResult",ColumnType.Boolean },
            {"ThirdConfirmResult",ColumnType.Boolean },
            {"RecordItem",ColumnType.Text },
            {"MeasuredActual",ColumnType.Text },
        };

        public static BopTree ReadJson(string bopFileName)
        {
            var filePath = Path.GetDirectoryName(bopFileName);
            var jobj = JsonConvert.DeserializeObject<JObject>(LoadJsonFile(bopFileName));
            var bopTree = new BopTree();
            bopTree.Nodes = new List<BopNode>();
            var name = jobj.Value<string>("Name");
            var id = jobj.Value<string>("Id");
            var nodes = jobj.Value<JArray>("Nodes");
            bopTree.Name = name;
            bopTree.Id = Guid.Parse(id);
            foreach (var it in nodes)
            {
                bopTree.Nodes.Add(LoadNode(it, filePath,bopTree.Id));
            }
            return bopTree;
        }
        private static BopNode LoadNode(JToken jToken,string basePath,Guid bopTreeId)
        {
            var result = jToken.ToObject<BopNode>();
            result.BopTreeId = bopTreeId;
            result.ProcessSpecifications = new List<FileProcessSpecification>();
            var fileName = jToken.Value<string>("FileName");

            //加载规程信息
            var fps = LoadProcessSpecification(Path.Combine(basePath, fileName),bopTreeId,result.Id);
            result.ProcessSpecifications.Add(fps);
            //查看是否有子节点并加载
            var childNodes = jToken.Value<JArray>("Nodes");
            if (childNodes != null && childNodes.HasValues)
            {
                result.Nodes = new List<BopNode>();
                foreach (var it in childNodes)
                {
                    result.Nodes.Add(LoadNode(it,basePath, bopTreeId));
                }
            }
            return result;
        }
        /// <summary>
        /// 加载json文件并返回全部字符
        /// </summary>
        /// <param name="fileName">文件路径</param>
        /// <returns></returns>
        private static string LoadJsonFile(string fileName)
        {
            using (var sr = new StreamReader(fileName))
            {
                return sr.ReadToEnd();
            }
        }
        private static FileProcessSpecification LoadProcessSpecification(string path,Guid bopTreeId,Guid bopNodeId)
        {
            var jobj = JsonConvert.DeserializeObject<JObject>(LoadJsonFile(path));
            var fps = jobj.ToObject<FileProcessSpecification>();
            fps.BopTreeId = bopTreeId;
            fps.BopNodeId = bopNodeId;
            fps.Status = FileProcessSpecificationStatus.Unset;
            fps = LoadTechniqueTask(fps,jobj.Value<JToken>("TechniqueTask"),fps.Id);
            return fps;
        }
        private static FileProcessSpecification LoadTechniqueTask(FileProcessSpecification fps,JToken jToken, Guid fileProcessSpecificationId)
        {
            var ftt = jToken.ToObject<FileTechniqueTask>();
            ftt.FileProcesses = LoadProcessesList(ftt, jToken.Value<JArray>("ProcessesListDto"),ftt.Id,fileProcessSpecificationId);
            fps.FileTechniqueTask = ftt;
            return fps;
        }
        private static ICollection<FileProcesses> LoadProcessesList(FileTechniqueTask ftt, JArray jArray, Guid fileTechniqueTaskId, Guid fileProcessSpecificationId)
        {
            var result = new List<FileProcesses>();
            foreach(var it in jArray)
            {
                var itfp = it.ToObject<FileProcesses>();
                itfp.FileTechniqueTaskId = fileTechniqueTaskId;
                itfp.FileProcessSpecificationId = fileProcessSpecificationId;
                
                itfp.FileWorkSteps = LoadWorkStepList(itfp, it.Value<JArray>("WorkStepListDto"));
                result.Add(itfp);
            }
            return result;
        }
        private static ICollection<FileWorkStep> LoadWorkStepList(FileProcesses fp, JArray jArray)
        {
            var result = new List<FileWorkStep>();
            foreach (var it in jArray)
            {
                var itws = it.ToObject<FileWorkStep>();
                itws.TWorkStepContent = itws.WorkStepName + itws.WorkStepContent;
                //加载填充等信息
                itws.FileTables =  LoadTables(it, itws.ProcessesEntityId.ToString(), itws.Id.ToString());
                result.Add(itws);
            }
            return result;
        }
        private static ICollection<FileTable> LoadTables(JToken jToken,string processId,string stepId)
        {
            var result = new List<FileTable>();
            foreach(var jProperty in jToken.Children<JProperty>())
            {
                var it = jToken.Value<JToken>(jProperty.Name);
                if(it.Type == JTokenType.Array)
                {
                    var value = it.ToObject<JArray>();
                    if(value.Count > 0)
                    {
                        var tableItem = new FileTable();
                        var key = jProperty.Name;
                        tableItem.TableFieldName = key;
                        tableItem.FileProcessesId = processId;
                        tableItem.FileWorkStepId = stepId;
                        //TODO: 根据数据库中的数据判断是否是动态表格
                        var isDynamicTable = key.Equals("ManufacturingResources") || key.Equals("InsertDetails");
                        if (isDynamicTable)
                        {
                            tableItem.DynamicTable = false;
                            var fileStruct = new List<FileTableStruce>();
                            if (key.Equals("ManufacturingResources"))
                            {
                                tableItem.TableName = "制造资源";
                                fileStruct.Add(new FileTableStruce() { FieldName = "Type", DisplayName = "类型", Enable = false, Show = true, Property = 0, ColumnType = ColumnType.Text });
                                fileStruct.Add(new FileTableStruce() { FieldName = "ErpId", DisplayName = "ERPID", Enable = false, Show = true, Property = 0, ColumnType = ColumnType.Text });
                                fileStruct.Add(new FileTableStruce() { FieldName = "SpecsCode", DisplayName = "代号或规格", Enable = false, Show = true, Property = 0, ColumnType = ColumnType.Text });
                                fileStruct.Add(new FileTableStruce() { FieldName = "Name", DisplayName = "名称", Enable = false, Show = true, Property = 0, ColumnType = ColumnType.Text });
                                fileStruct.Add(new FileTableStruce() { FieldName = "Remark", DisplayName = "备注", Enable = false, Show = true, Property = 0, ColumnType = ColumnType.Text });
                                fileStruct.Add(new FileTableStruce() { FieldName = "IdentifyType", DisplayName = "鉴定类别", Enable = false, Show = true, Property = 0, ColumnType = ColumnType.Text });
                                fileStruct.Add(new FileTableStruce() { FieldName = "StandardNumber", DisplayName = "标准号", Enable = false, Show = true, Property = 0, ColumnType = ColumnType.Text });
                                fileStruct.Add(new FileTableStruce() { FieldName = "IsRequired", DisplayName = "是否必选", Enable = false, Show = true, Property = 0, ColumnType = ColumnType.Text });
                            }
                            else if (key.Equals("InsertDetails"))
                            {
                                tableItem.TableName = "装入件明细";
                                fileStruct.Add(new FileTableStruce() { FieldName = "Code", DisplayName = "代号", Enable = false, Show = true, Property = 0, ColumnType = ColumnType.Text });
                                fileStruct.Add(new FileTableStruce() { FieldName = "Name", DisplayName = "名称", Enable = false, Show = true, Property = 0, ColumnType = ColumnType.Text });
                                fileStruct.Add(new FileTableStruce() { FieldName = "Number", DisplayName = "数量", Enable = false, Show = true, Property = 0, ColumnType = ColumnType.Text });
                                fileStruct.Add(new FileTableStruce() { FieldName = "Remark", DisplayName = "备注", Enable = false, Show = true, Property = 0, ColumnType = ColumnType.Text });
                            }
                            tableItem.FileTableStruces = fileStruct;
                            tableItem.FileTableRows = LoadTableDatas(value, fileStruct);
                        }
                        else
                        {
                            var value0 = value.First;
                            var ForName = value0.Value<string>("FormName");
                            if(ForName != null)
                            {
                                var hasInspectionSignature = value0.Value<string>("InspectionSignatureName") != null;
                                tableItem.TableName = ForName;
                                tableItem.HasInspectionSignature = hasInspectionSignature;
                                tableItem.DynamicTable = true;
                                tableItem.FileTableStruces = LoadTableStructs(value0);
                                tableItem.FileTableRows = LoadTableDatas(value, tableItem.FileTableStruces);
                            }
                            
                            
                        }
                        result.Add(tableItem);
                    }
                }
            }
            return result;
        }
        private static ICollection<FileTableRow> LoadTableDatas(JArray jArray,ICollection<FileTableStruce> fileTableStruces)
        {
            var result = new List<FileTableRow>();
            foreach(var jobj in jArray)
            {
                var item = new FileTableRow();
                item.FileTableDatas = new List<FileTableData>();
                item.Id = Guid.Parse(jobj.Value<string>("Id"));
                foreach (var it in fileTableStruces)
                {
                    var dataItem = new FileTableData();
                    dataItem.FieldName = it.FieldName;
                    dataItem.DisplayName = it.DisplayName;
                    dataItem.Enable = it.Enable;
                    dataItem.Show = it.Show;
                    dataItem.Property = it.Property;
                    dataItem.ColumnType = it.ColumnType;
                    dataItem.Value = jobj.Value<string>(it.FieldName);
                    item.FileTableDatas.Add(dataItem);
                }
                result.Add(item);
            }
            return result;
        }
        private static ICollection<FileTableStruce> LoadTableStructs(JToken jToken)
        {
            var result = new List<FileTableStruce>();
            foreach(var jProperty in jToken.Children<JProperty>())
            {
                var it = jToken.Value<JToken>(jProperty.Name);
                var key = jProperty.Name;
                if (DynamicField.ContainsKey(key))
                {
                    var structItem = new FileTableStruce()
                    {
                        FieldName = key,
                        DisplayName = jToken.Value<string>($"{key}_DisplayName"),
                        Enable = jToken.Value<bool>($"{key}_Enable"),
                        Show = jToken.Value<bool>($"{key}_Show"),
                        Property = jToken.Value<int>($"{key}_Property"),
                        ColumnType = DynamicField[key]
                    };
                    result.Add(structItem);

                }
            }
            return result;
        }
    }
}
